import React, { ChangeEvent, createRef, useCallback, useContext, useEffect, useState } from "react";
import { Accordion, Button, Container, Dropdown, DropdownButton, Form, FormGroup, InputGroup, ListGroup } from "react-bootstrap";
import { useNavigate } from "react-router-dom";
import ChatService from "../../../services/chatservice";
import { PopupDialog } from "../../../components/common";
import { ThreeDots } from "react-bootstrap-icons";
import { UserHelper } from "../../../helper";
import EditContact from "./edit";
import './index.css';
import AuthenticationContext from "../../../context/Context";

interface ChatContact{
    username:string;
    nickname?:string;
    userid:string;
    isContact:boolean;
    opstatus:number;
    action:number;
    contactalias?:string;//current user give his contact a name.
    tag?:string;
    contactgroup?:string;
}

class ChatContactGroup{
    contacts?:Array<ChatContact>;
    contactgroup?:string;
    constructor(props:{contactgroup:string,contacts:Array<ChatContact>}){
        this.contactgroup = props.contactgroup;
        this.contacts = props.contacts;
    }
}

interface ChatContactProps{
    contactList?:Array<ChatContact>;
    contactGroups?:Array<ChatContactGroup>;
}

const ChatContact:React.FC<ChatContactProps> = (props:ChatContactProps)=> {

    const navigate = useNavigate();
    const [inSearch,setInSearch] = useState(false);
    const [searchText,setSearchText] = useState<string>();
    const [searchResults,setSearchResult] = useState<Array<ChatContact>>(props.contactList||[]);
    const [originContactList,setOriginContactList] = useState<Array<ChatContact>>(props.contactList||[]);
    const [contactGroups,setContactGroups] = useState<Array<ChatContactGroup>>(props.contactGroups||[]);

    const {userInfo} = useContext(AuthenticationContext);

    const onPressContact = (contact:ChatContact)=> {
        navigate("/chat/dialog",{
            state:{
                contact:contact
            }
        });
    }
    //
    useEffect(()=>{
        refreshContactList();
    },[])

    const refreshContactList = ()=> {
        //group by tag.
        ChatService.getContacts(userInfo.userid).then((contactList=[])=>{
            console.debug(`get contact list: ${contactList}`);
            const cl = contactList
            setOriginContactList(cl);
            var groupNames:Array<string> = [];
            contactList.forEach((contact,idx)=>{
                var group = contact.contactGroup||"Default";
                if(!groupNames.includes(group)){
                    groupNames.push(group);
                }
            })
            var contactGroups:Array<ChatContactGroup> = [];
            groupNames.forEach((groupName,idx)=>{
                var contacts = contactList.filter((contact,idx)=>{
                    return contact.contactGroup === groupName || !contact.contactGroup;
                })
                var myDefinedGroup = new ChatContactGroup({contactgroup:groupName,contacts});
                contactGroups.push(myDefinedGroup);
            })
            setContactGroups(contactGroups);
        })
    }

    const onClickSearch = ()=> {
        if(!inSearch && searchText && searchText.length > 0){
            ChatService.searchContact(userInfo.userid,searchText).then((contactList)=>{
                console.debug(`get contact list: ${contactList||[]}`);
                setSearchResult(contactList);
            }).catch((err)=>{
                PopupDialog.showBsError(err);
            })    
        }else{
            setSearchText("")
            setSearchResult(originContactList);
        }
        setInSearch(!inSearch);
    }

    const onChange = (e:ChangeEvent<HTMLInputElement>)=> {
        e.preventDefault();
        var text = e.target.value;
        setSearchText(text);
        setInSearch(false);
    }

    const addContact = useCallback((userid:string,contactid:string)=> {
        ChatService.addAcceptContact({
            userid:userid,
            contactid:contactid,
            type:"0"
        }).then((result)=>{
            console.debug(`got result from server ${result}`);
            PopupDialog.showBSPopup({message:"Send add contact request successfully!"});
            refreshContactList();
        }).catch((err)=>{
            PopupDialog.showBsError(err);
        })
    },[])

    const acceptContact = (userid:string,contactid:string)=>{
        acceptOrReject(userid,contactid,"1");
    }

    const rejectContact = (userid:string,contactid:string)=>{
        acceptOrReject(userid,contactid,"2");
    }

    const acceptOrReject = (userid:string,contactid:string,optype:string)=>{
        ChatService.addAcceptContact({
            userid:userid,
            contactid:contactid,
            type:optype
        }).then((result)=>{
            console.debug(`got result from server ${result}`);
            PopupDialog.showBSPopup({message:"Successfully accept the request!"});
            refreshContactList();
        }).catch((err)=>{
            PopupDialog.showBsError(err);
        })
    }

    const onSelect = (eventKey: string | null, contact:ChatContact)=>{
        if(eventKey === 'delete'){
            PopupDialog.showBSPopup({
                message:"Do you want to delete this contact?",
                showCancelButton:true,
                cancelButtonPosition:'start'
            },
            ()=>{
                ChatService.deleteContact({
                    ownerId:userInfo.userid,
                    contactId:contact.userid
                }).then(()=>{
                    PopupDialog.showBSPopup({message:"Delete success!"});
                    refreshContactList();
                }).catch((err)=>{
                    PopupDialog.showBsError(err);
                })
            })
        }else if(eventKey === 'add'){
            addContact(userInfo.userid,contact.userid);
        }else if(eventKey === 'edit'){
            navigate("/chat/contact/edit",{state:contact});
        }
    }

    const renderContact = (contact:ChatContact,index:number) => {
        return (<ListGroup.Item key={`${contact.userid}`}>
        <Container fluid className="d-flex flex-row justify-content-between p-0">
            <Container 
                fluid
                className="d-flex flex-row align-items-center justify-content-between p-0 m-0 px-2"
                style={{flex:1}}
                onClick={()=>{
                    if(contact.opstatus !== 1){
                        return;
                    }
                    onPressContact(contact);
                }}
            >
                <p>{`${contact.action === 1 ? "friend request from ":""}${contact.nickname||contact.username}`}</p>
                {contact.action === 1 ? (<div className="d-flex flex-row">
                    <Button size="sm" onClick={(e)=>{
                        e.preventDefault();
                        acceptContact(userInfo.userid,contact.userid);
                    }}>Accept</Button>&nbsp;
                    <Button size="sm" variant="danger" onClick={(e)=>{
                        e.preventDefault();
                        PopupDialog.showBSPopup({message:"Are you wanna reject this request?",showCancelButton:true},()=>{
                            rejectContact(userInfo.userid,contact.userid);
                        })
                    }}>Reject</Button>
                </div>):(contact.opstatus === 0 && <p style={{fontSize:11}}>Pending accept</p>)}
                {contact.userid == userInfo.userid ? <i>It's Yourself</i>:""}
            </Container>
            {contact.userid !== userInfo.userid && contact.opstatus !== 0 && <DropdownButton 
                drop="start" 
                variant="light"
                title={<ThreeDots />}
                onSelect={(eventKey: string | null, e: React.SyntheticEvent<unknown>)=>{
                    e.stopPropagation();
                    onSelect(eventKey,contact);
                }}
                >
                {contact.opstatus === -1 && <Dropdown.Item eventKey={"add"}>Add</Dropdown.Item>}
                {contact.opstatus === 1 && (<>
                    <Dropdown.Item className="text-primary" eventKey={"edit"}>Edit</Dropdown.Item>
                    <Dropdown.Item className="text-danger" eventKey={"delete"}>Delete</Dropdown.Item>
                </>)}
            </DropdownButton>}
        </Container>
    </ListGroup.Item>)
    }

    const showSearchContacts = ()=> {
        return searchResults?.map((contact,index)=>{
            return renderContact(contact,index);
        })
    }

    const showMyGroups = ()=> {
        return (<ListGroup.Item className="border-0">
            <Accordion defaultActiveKey={'group-Default'}>
                {contactGroups.map((group,idx)=>{
                    return (<Accordion.Item key={`${group.contactgroup}`} eventKey={`group-${group.contactgroup||"Default"}`}>
                            <Accordion.Header>{group.contactgroup}</Accordion.Header>
                        <Accordion.Body className="m-0 p-0">
                            {<ListGroup>
                                {group.contacts?.map((contact,index)=>{
                                    return renderContact(contact,10000+index);
                                })}    
                            </ListGroup>}
                        </Accordion.Body>
                        </Accordion.Item>)
                })}
                </Accordion>
        </ListGroup.Item>)
    }

    return (<Container fluid className="d-flex flex-column m-0 p-0">
        <ListGroup>
            <ListGroup.Item key={"list-search"}>
                <FormGroup className="d-flex">
                    <InputGroup>
                        <Form.Control 
                            size="sm"
                            defaultValue={searchText}
                            type="input" 
                            placeholder="Please input the contact name or contact id"
                            onFocus={()=>{
                                setInSearch(true);
                            }}
                            onBlur={()=>{
                                setInSearch(false);
                            }}
                            onChange={onChange}
                            />
                        <Button onClick={onClickSearch}>{inSearch ? "Cancel":"Search"}</Button>
                    </InputGroup>
                </FormGroup>
            </ListGroup.Item>
            {inSearch ? showSearchContacts() : showMyGroups()}
        </ListGroup>
    </Container>)
}

ChatContact.defaultProps = {
    contactList:[
    ]
}

export default ChatContact;
export {EditContact};